package com.zqh.synchronizedDemo;

import java.util.*;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * test Lock Condition
 */
public class Bank {
    private final double[] accounts;
    private Lock bankLock;
    private Condition sufficientFunds;

    public Bank(int n, double initialBalance)
    {
        accounts = new double[n];
        Arrays.fill(accounts,initialBalance);
        bankLock = new ReentrantLock();
        sufficientFunds = bankLock.newCondition();
    }
    /*public void transfer(int from, int to, double amount) throws InterruptedException {
        //System.out.println("from "+from+" to "+to);
        bankLock.lock();
        try{
            while(accounts[from] < amount){
                sufficientFunds.await();
            }
            System.out.print(Thread.currentThread().getName()+" ");
            accounts[from] -= amount;
            System.out.printf("%10.2f from %d to %d",amount,from,to);
            accounts[to] += amount;
            System.out.printf(" Total Balance: %10.2f%n",getTotalBalance());
            sufficientFunds.signalAll();
        }finally {
            bankLock.unlock();
        }

    }*/
    public synchronized void transfer(int from, int to, double amount) throws InterruptedException {
        while(accounts[from] < amount){
            wait();
        }
        System.out.print(Thread.currentThread().getName()+" ");
        accounts[from] -= amount;
        System.out.printf("%10.2f from %d to %d",amount,from,to);
        accounts[to] += amount;
        System.out.printf(" Total Balance: %10.2f%n",getTotalBalance());
        notifyAll();
    }

    /*public double getTotalBalance(){
        bankLock.lock();
        try{
            double sum = 0;
            for (double a : accounts){
                sum += a;
            }
            return sum;
        }finally {
            bankLock.unlock();
        }
    }*/
    public synchronized double getTotalBalance(){
        double sum = 0;
        for (double a : accounts){
            sum += a;
        }
        return sum;
    }

    public int size(){
        return accounts.length;
    }

    public static void main(String[] args) {
       /* Bank bank = new Bank(10,1000);
        for (int i = 0; i<10; i++){
            new Thread(()->{
                try {
                    bank.transfer((int)(Math.random()*10),(int)(Math.random()*10),
                        Math.random()* 1000-1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }*/
        LongAccumulator tes = new LongAccumulator(Math::multiplyExact,11);
        //tes.accumulate(12);
        tes.accumulate(13);
        System.out.println(tes.get());
    }
}
